/**
Q:Go语言中的defer关键字有什么作用？
A:defer关键字用于延迟函数的执行，即在函数退出前执行某个操作
defer通常用于释放资源，关闭文件，解锁互斥锁等清理操作，以确保在函数执行完毕后进行处理
*/

package main

import (
	"fmt"
	"os"
	"strconv"
)

func main() {
	file, err := os.Open("D:\\6-1-leetcode\\Go-Interview-Questions\\2\\file.txt")
	if err != nil {
		fmt.Println(err)
		return
	}

	defer func() {
		err := file.Close()
		if err != nil {
			fmt.Println(err)
		}
	}()
	content := make([]byte, 20)
	n, err := file.Read(content)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("total length " + strconv.Itoa(n))
	fmt.Println(string(content))

	fmt.Println("File operation completed")

	deferTest()
}

/*
在上述代码中，我们使用defer关键字延迟了文件的关闭操作，确保在函数执行完毕后关闭文件。这样可以避免忘记关闭文件而导致资源泄漏。
*/

func deferTest() {
	defer func() {
		fmt.Println("defer 1")
	}()

	defer func() {
		fmt.Println("defer 2")
	}()

	fmt.Println("main")

	/*
			result:
				main
				defer 2
				defer 1

		defer函数栈 先进后出 后进先出
	*/
}

/*
在上面的代码中，我们定义了两个defer语句，它们分别输出"defer 1"和"defer 2"。
这两个defer语句的执行顺序是先进后出的，也就是说后定义的defer语句先执行，先定义的defer语句后执行。
因此，输出的顺序应该是"main"、"defer 2"、"defer 1"。

这个例子也展示了defer语句的另一个特性，即在函数返回前执行。
在main函数返回前，两个defer语句分别执行了它们的函数体，输出了相应的内容。
这种特性可以用于释放资源、关闭连接等操作，在函数返回前保证它们被执行。

需要注意的是，defer语句并不是一种异步操作，它只是将被延迟执行的函数加入到一个栈中，在函数返回前按照后进先出的顺序执行。
因此，在defer语句中的函数应该是轻量级的，避免影响程序的性能。
同时，也需要注意defer语句的执行顺序和函数返回时的状态，避免出现不符合预期的结果。
*/
